package com.faxsun.web.controller.news;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import mblog.core.pojos.Post;
import mblog.core.pojos.Tag;
import mblog.web.controller.BaseController;
import mtons.modules.pojos.Page;
import mtons.modules.pojos.UserContextHolder;
import mtons.modules.pojos.UserProfile;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.faxsun.core.pojos.enums.PostType;
import com.faxsun.core.service.AggregationService;
import com.faxsun.core.service.IndexService;
import com.faxsun.core.service.PostService;
import com.faxsun.core.service.TagService;
import com.faxsun.pojos.TagAggregation;
import com.faxsun.web.controller.FrontViewConstants;
import com.faxsun.web.utils.MobileDetect;
import com.faxsun.web.utils.VisiblePage;

@Controller
@RequestMapping("/news")
public class NewsController extends BaseController {

	@SuppressWarnings("unused")
	private static final Logger LOG = LoggerFactory
			.getLogger(NewsController.class);

	private static final int NEWS_PAGINATION_SIZE = 10;

	private static final int NEWS_RECENT_FETCHSIZE = 1000;

	private static final int NEWS_PAGINATION_DFLT_VISIBLE_SIZE = 5;

	@Autowired
	protected PostService postService;

	@Autowired
	protected AggregationService newsAggregation;

	@Autowired
	protected TagService tagService;

	// 使用IndexService的热门资讯
	@Autowired
	private IndexService indexService;

	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public String list(ModelMap model, HttpServletRequest request) {
		loadPage(model, request, 1, Collections.<String> emptyList());
		model.addAttribute("navigation", "news");
		fillRightColumnArticals(model);
		String viewUrl = MobileDetect.getProperView(request,
				"/views/mobile/infoList", FrontViewConstants.VIEW_INFO_LIST);
		return viewUrl;
	}

	@RequestMapping(value = "/paging", method = RequestMethod.POST)
	public String paging(ModelMap model, HttpServletRequest request) {
		// long userId = getUserId();
		String targetPage = request.getParameter("page");
		String[] tagIds = request.getParameterValues("tagIds");
		if (tagIds != null && tagIds.length > 0) {
			loadPage(model, request, Integer.parseInt(targetPage),
					new ArrayList<String>(Arrays.asList(tagIds)));
		} else {
			loadPage(model, request, Integer.parseInt(targetPage),
					Collections.<String> emptyList());
		}
		return FrontViewConstants.VIEW_INFO_VERTICAL_LIST;
	}

	@SuppressWarnings("unchecked")
	private void loadPage(ModelMap model, HttpServletRequest request,
			int targetPageId, List<String> tags) {
		int totalNewsSize = 0;
		if (tags != null && tags.size() > 0) {
			totalNewsSize = postService.countRecentNewsForTag(-1, tags);
		} else {
			totalNewsSize = postService.countRecentNews(NEWS_RECENT_FETCHSIZE,
					-1);
		}

		int curPageId = targetPageId;

		// add max page
		int maxPageId = (totalNewsSize / NEWS_PAGINATION_SIZE)
				+ (totalNewsSize % NEWS_PAGINATION_SIZE == 0 ? 0 : 1);
		if (curPageId > maxPageId) {
			curPageId = maxPageId;
		}
		model.addAttribute("maxPage", maxPageId);
		model.addAttribute("curPage", curPageId);
		model.addAttribute("prevPage", curPageId - 1 < 1 ? 1 : curPageId - 1);
		model.addAttribute("nextPage", curPageId + 1 > maxPageId ? maxPageId
				: curPageId + 1);

		// add paging post url
		String contextPath = request.getContextPath();
		String url = null;
		if (tags != null && tags.size() > 0) {
			url = contextPath + "/news/paging?";
			for (int i = 0; i < tags.size(); i++) {
				if (i > 0) {
					url += "&";
				}
				url += "tagIds=" + tags.get(i);
			}
		} else {
			url = contextPath + "/news/paging";
		}
		model.addAttribute("url", url);

		// add visible page for pagination
		List<VisiblePage> visiblePages = new ArrayList<VisiblePage>(
				NEWS_PAGINATION_DFLT_VISIBLE_SIZE);
		int startPageId = curPageId - 2 < 1 ? 1 : curPageId - 2;
		int endPageId = curPageId + 2 > maxPageId ? maxPageId : curPageId + 2;
		for (int i = startPageId; i <= endPageId; i++) {
			VisiblePage vp = new VisiblePage();
			vp.setId(i);
			if (i == curPageId) {
				vp.setCurPage(true);
			}
			visiblePages.add(vp);
		}
		model.addAttribute("visiblePages", visiblePages);

		List<Tag> navTags = tagService.listNavTags(1);
		for (Tag tag : navTags) {
			if (tags.contains(tag.getName())) {
				tag.setCurTag(true);
			} else {
				tag.setCurTag(false);
			}
		}
		model.addAttribute("tagNav", navTags);

		// add news for current page
		List<Post> news = Collections.EMPTY_LIST;
		Page page = wrapPage(curPageId);
		page.setMaxResults(NEWS_PAGINATION_SIZE);

		if (tags != null && tags.size() > 0) {
			List<Tag> ts = new ArrayList<Tag>(tags.size());
			for (String tag : tags) {
				ts.add(new Tag(tag));
			}
			TagAggregation infoAggregation = newsAggregation
					.aggregateInfosByTags(page, ts);
			news = infoAggregation.getInfos();
			// 将待查询的tag放到前面
			for (Post blog : news) {
				String tagStrings = blog.getTags();
				// FIXME use StringBuffer instead of String
				for (Tag t : ts) {
					if (tagStrings.contains(t.getName())) {
						tagStrings = t.getName() + "," + tagStrings;
						blog.setTags(tagStrings);
						break;
					}
				}
			}
		} else {
			postService.paging(page, PostType.INFO);
			if (page.getSize() > 0) {
				news = (List<Post>) page.getResults();
			}
		}
		model.addAttribute("news", news);
	}

	/**
	 * 根据标签id，过滤显示资讯文章
	 * 
	 * @param tagIdStr
	 *            标签ID
	 * @param model
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "/list/filter", method = RequestMethod.GET)
	public String listByTag(
			@RequestParam(value = "tagIds") List<String> tagIdStr,
			ModelMap model, HttpServletRequest request) {
		// long userId = getUserId();
		loadPage(model, request, 1, tagIdStr);
		model.addAttribute("navigation", "news");
		fillRightColumnArticals(model);

		String viewUrl = MobileDetect.getProperView(request,
				"/views/mobile/infoList", FrontViewConstants.VIEW_INFO_LIST);
		return viewUrl;
	}

	@SuppressWarnings("unused")
	private long getUserId() {
		UserProfile up = UserContextHolder.getUserProfile();
		long userId = 1;
		if (up != null) {
			userId = up.getId();
		}
		return userId;
	}

	private void fillRightColumnArticals(ModelMap model) {
		// 热门资讯
		Page hotInfoPage = wrapPage(1);
		hotInfoPage.setMaxResults(4);
		indexService.retrieveHotInfo(hotInfoPage);
		model.addAttribute("hotNews", hotInfoPage.getResults());

		// 最近资讯
		Page recentNews = wrapPage(1);
		recentNews.setMaxResults(4);
		postService.findRecentPosts(recentNews, PostType.INFO);
		model.addAttribute("recentNews", recentNews.getResults());
	}

	@RequestMapping(value = "/news-json", method = RequestMethod.POST)
	@ResponseBody
	public List<Post> json(HttpServletRequest request,
			HttpServletResponse response,
			@RequestParam(value = "pagNo", required = false) Integer pageNo,
			ModelMap model) {

		loadPage(model, request, pageNo, Collections.<String> emptyList());
		@SuppressWarnings("unchecked")
		List<Post> news = (List<Post>) model.get("news");
		return news;
	}

	@SuppressWarnings("unchecked")
	@RequestMapping(value = "/json", method = RequestMethod.POST)
	@ResponseBody
	public List<Post> listByTagPost(
			@RequestParam(value = "tagIds") List<String> tags,
			@RequestParam(value = "pagNo", required = false) Integer pageNo,
			@RequestParam(value = "max", required = false) Integer maxResults,
			ModelMap model, HttpServletRequest request,
			HttpServletResponse response) {

		List<Post> news = Collections.emptyList();
		Page page = wrapPage(pageNo);
		page.setMaxResults(NEWS_PAGINATION_SIZE);

		if (tags != null && tags.size() > 0) {
			List<Tag> ts = new ArrayList<Tag>(tags.size());
			for (String tag : tags) {
				ts.add(new Tag(tag));
			}
			TagAggregation infoAggregation = newsAggregation
					.aggregateInfosByTags(page, ts);
			news = infoAggregation.getInfos();
		} else {
			postService.paging(page, PostType.INFO);
			if (page.getSize() > 0) {
				news = (List<Post>) page.getResults();
			}
		}

		int maxPageId = (postService.countRecentNewsForTag(-1, tags) / NEWS_PAGINATION_SIZE) + 1;
		if (pageNo > maxPageId) {
			return Collections.emptyList();
		} else {
			return news;
		}

	}
}
